#!/usr/bin/python
### -*- coding: UTF-8 -*-

import json, random
from flask import Flask, request, Response, render_template, jsonify
from db import *

import spidertool.handle_url as hu
import spidertool.handle_nums_per_month
import spidertool.wikipedia as wiki
import spidertool.community_info as ci
import spidertool.git_stat as gt
import spidertool.codeLanguage as cl
import spidertool.codeInfo
import spidertool.handle_bbs
import os

########## 公共方法
##### 返回页面
def rpage(page):
    return render_template(page + '.html')
##### 返回列表字典时转JSON
class Res(Response):
    @classmethod
    def force_type(cls, response, environ=None):
        if isinstance(response, (list, dict)):
            response = jsonify(response)
        return super(Response, cls).force_type(response, environ)
##### 遍历project_inf找值
def f(data, key):
    for x in data:
        if x['key_name'] == key:
            return x['key_val']
    return ''
##### 随机数
def r():
    return random.randint(1, 1000)
##### JSON文件
def q(json_file):
    with open('temp/' + json_file) as json_str:
        return json.load(json_str)


########## Flask配置
app = Flask(__name__)
app.response_class = Res
app.config.from_object(__name__)
app.secret_key = 'spider'


########## 页面接口
##### 主页
@app.route('/', methods=['GET'])
def index():
    return rpage('index')
@app.route('/search', methods=['POST'])
def search():
    keywords = request.form.get("keywords", type=str, default=None)
    #爬虫获得链接并返回
    # return { "openhub": [{ "name": "GOGOPang", "path": "asdfasdf" }, { "name": "ASDFASDF", "path": "ASDFASDF" }, { "name": "HPCC Streaming with Apache Kafka", "path": "kafka-integration" }], "github": [{ "name": "apache/kafka", "path": "apache/kafka" }, { "name": "kafka-dev/kafka", "path": "kafka-dev/kafka" }, { "name": "pinterest/secor", "path": "pinterest/secor" }] }
    sta = os.system('./spidertool/geturl.sh ' + keywords)
    print 'sta:%s' %(sta)
    if (sta == 0):

        # print hu.get_url_json()

        print hu.get_url_json()

        return hu.get_url_json()

@app.route('/start', methods=['POST'])
def start():
    if request.form['keywords'] == None or request.form['pname'] == None or request.form['github'] == None or request.form['openhub'] == None:
        return { "msg": "参数错误" }
    id = task_record.insert({
        'keywords': request.form['keywords'],
        'pname': request.form['pname'],
        'github': request.form['github'],
        'openhub': request.form['openhub'],
        'pstat': '0%'
        })
    if id < 0:
        return { "msg": "插入task_record失败" }
    #开启任务的所有子爬虫，任务创建完成，返回到前端
    
    return { "msg": "ok", "tid": id }

##### 历史
@app.route('/history', methods=['GET'])
def history():
    return rpage('history')
@app.route('/history/list', methods=['GET'])
def history_list():
    return task_record.findall()

##### 报告
@app.route('/<int:tid>', methods=['GET'])
def report(tid):
    return rpage('report')
### 基本
@app.route('/<int:tid>/info', methods=['GET'])
def report_info(tid):
    #查询项目信息表中键为info_开头的数据
    data = project_inf.findby_tid_key(tid, 'info_')
    if len(data) == 0:
        #库中没有数据时去爬虫获取，爬完返回构造data字典：
        # 需要维基百科的url
        url = ""
        data = wiki.get_wiki(tid, 'https://en.wikipedia.org/wiki/Apache_Kafka')
        # data = [
        #     {'tid': tid, 'key_name': 'info_name', 'key_val': 'Apache Kafka' },
        #     {'tid': tid, 'key_name': 'info_tags', 'key_val': 'messaging,nosql,pubsub,queuing' },
        #     {'tid': tid, 'key_name': 'info_dever', 'key_val': 'Apache软件基金会' },
        #     {'tid': tid, 'key_name': 'info_initVer', 'key_val': '2016年1月' },
        #     {'tid': tid, 'key_name': 'info_stableVer', 'key_val': '0.11.0.1（2016年12月）' },
        #     {'tid': tid, 'key_name': 'info_devStat', 'key_val': '非常活跃' },
        #     {'tid': tid, 'key_name': 'info_codeLangs', 'key_val': 'Java, Scala' },
        #     {'tid': tid, 'key_name': 'info_os', 'key_val': '跨平台' },
        #     {'tid': tid, 'key_name': 'info_type', 'key_val': '流式处理，消息中间件' },
        #     {'tid': tid, 'key_name': 'info_license', 'key_val': 'Apache 2.0'}
        # ]
        #保存到数据库
        if project_inf.replace(data) < 0:
            return { "msg": "插入project_inf失败" }
    #返回data字典的数据到前端
    return {
        'name': f(data, 'info_name'),
        'tags':f(data, 'info_tags').split(','),
        "dever": f(data, 'info_dever'),
        'initVer': f(data, 'info_initVer'),
        'stableVer': f(data, 'info_stableVer'),
        'devStat': f(data, 'info_devStat'),
        'codeLangs': f(data, 'info_codeLangs'),
        'os': f(data, 'info_os'),
        'type': f(data, 'info_type'),
        'license': f(data, 'info_license')
    }
### 社区
@app.route('/<int:tid>/community/info', methods=['GET','PUT'])
def community_info(tid):
    data = None
    if request.method == 'GET':
        #查询项目信息表中键为info_开头的数据
        data = project_inf.findby_tid_key(tid, 'community_')
    if data is None or len(data) == 0:
        #请求为PUT或库中没有数据时去爬虫获取，爬完返回构造data字典：
        # 此处替换为github_url

        res = task_record.findbyid(tid)
        url = res[0]['github']
        data = ci.get(tid, url)
        # data = ci.get(tid, 'https://github.com/apache/kafka')
        data = ci.get(tid, 'https://github.com/apache/kafka')

        # data = [
        #     {'tid': tid, 'key_name': 'community_commits', 'key_val': 4362 },
        #     {'tid': tid, 'key_name': 'community_contributors', 'key_val': 348 },
        #     {'tid': tid, 'key_name': 'community_branches', 'key_val': 18 },
        #     {'tid': tid, 'key_name': 'community_releases', 'key_val': 60 }
        # ]
        #保存到数据库
        if project_inf.replace(data) < 0:
            return { "msg": "插入project_inf失败" }
    #返回data字典的数据到前端
    return { 
        'commits': f(data, 'community_commits'),
        'contributors': f(data, 'community_contributors'),
        'branches': f(data, 'community_branches'),
        'releases': f(data, 'community_releases')
    }
@app.route('/<int:tid>/community/commits_contributors', methods=['GET','PUT'])
def community_commits_contributors(tid):
    data = None
    if request.method == 'GET':
        #查询贡献者提交量统计表
        data = commu_sta.findby_tid(tid)
    if data is None or len(data) == 0:
        #请求为PUT或库中没有数据时去爬虫获取，爬完返回构造data列表：
        res = task_record.findbyid(tid)
        url = res[0]['openhub']
        sta = os.system('./spidertool/get_commits_contributors.sh ' + str(tid) + ' ' + url)
        print 'sta:%s' %(sta)
        if (sta == 0):
            data = spidertool.handle_nums_per_month.get_data()
            # print data
            # print json.dumps(data)
        # data = [
        #     {'tid': tid, 'quarter': '2015Q1', 'commit': 348, 'contributor': 11 },
        #     {'tid': tid, 'quarter': '2015Q2', 'commit': 248, 'contributor': 14 },
        #     {'tid': tid, 'quarter': '2015Q3', 'commit': 334, 'contributor': 12 },
        #     {'tid': tid, 'quarter': '2015Q4', 'commit': 148, 'contributor': 18 }
        # ]
        #保存到数据库
        if commu_sta.replace(data) < 0:
            return { "msg": "插入commu_sta失败" }
    #根据data构造2.3.3示例的字典返回到前端
    res = {"commits":[],"contributors":[]}
    for datum in data:
        res["commits"].append([datum["quarter"], datum["commit"]])
        res["contributors"].append([datum["quarter"], datum["contributor"]])
    return res
    # return q('2.3.3.json')
@app.route('/<int:tid>/community/contributors_level', methods=['GET','PUT'])
def community_contributors_level(tid):
    data = None
    if request.method == 'GET':
        #查询贡献者等级信息表
        data = commu_contri_level.findby_tid(tid)
    if data is None or len(data) == 0:
        #请求为PUT或库中没有数据时去爬虫获取，爬完返回构造data列表：
        data = [
            {'tid': tid, 'lv': 1, 'num': r()},
            {'tid': tid, 'lv': 2, 'num': r()},
            {'tid': tid, 'lv': 3, 'num': r()},
            {'tid': tid, 'lv': 4, 'num': r()},
            {'tid': tid, 'lv': 5, 'num': r()},
            {'tid': tid, 'lv': 6, 'num': r()}
        ]
        #保存到数据库
        if commu_contri_level.replace(data) < 0:
            return { "msg": "插入commu_contri_level失败" }
    ret = {}
    for x in data:
        ret[x['lv']] = x['num']
    return ret
### 关注度
@app.route('/<int:tid>/activity/info', methods=['GET','PUT'])
def activity_info_(tid):
    data = None
    if request.method == 'GET':
        #查询项目信息表中键为activity1_开头的数据
        data = project_inf.findby_tid_key(tid, 'activity1_')
    if data is None or len(data) == 0:
        #请求为PUT或库中没有数据时去爬虫获取，爬完返回构造data字典：
        data = [
            {'tid': tid, 'key_name': 'activity1_last30day', 'key_val': '137个提交，39个贡献者，比上个月新增9个' },
            {'tid': tid, 'key_name': 'activity1_last12month', 'key_val': '1514个提交，同比增长17%；217个贡献者，同比增长7%' },
        ]
        #保存到数据库
        if project_inf.replace(data) < 0:
            return { "msg": "插入project_inf失败" }
    #返回data字典的数据到前端
    return {
        'last30day': f(data, 'activity1_last30day'),
        'last12month': f(data, 'activity1_last12month'),
    }
@app.route('/<int:tid>/activity/git_stat', methods=['GET','PUT'])
def activity_git_stat(tid):
    data = None
    if request.method == 'GET':
        #查询项目信息表中键为activity2_开头的数据
        data = project_inf.findby_tid_key(tid, 'activity2_')
    if data is None or len(data) == 0:
        #请求为PUT或库中没有数据时去爬虫获取，爬完返回构造data字典：
        # 改为github_url
        res = task_record.findbyid(tid)
        url = res[0]['github']
        data = gt.get(tid, url)
        # data = gt.get(tid, 'https://github.com/rabbitmq/rabbitmq-server')
        # data = [
        #     {'tid': tid, 'key_name': 'activity2_watch', 'key_val': r() },
        #     {'tid': tid, 'key_name': 'activity2_star', 'key_val': r() },
        #     {'tid': tid, 'key_name': 'activity2_fork', 'key_val': r() }
        # ]
        #保存到数据库
        if project_inf.replace(data) < 0:
            return { "msg": "插入project_inf失败" }
    #返回data字典的数据到前端
    return {
        'watch': f(data, 'activity2_watch'),
        'star': f(data, 'activity2_star'),
        'fork': f(data, 'activity2_fork')
    }
@app.route('/<int:tid>/activity/git_pull', methods=['GET','PUT'])
def activity_git_pull(tid):
    data = None
    if request.method == 'GET':
        #查询项目信息表中键为activity3_开头的数据
        data = project_inf.findby_tid_key(tid, 'activity3_')
    if data is None or len(data) == 0:
        #请求为PUT或库中没有数据时去爬虫获取，爬完返回构造data字典：
        data = [
            {'tid': tid, 'key_name': 'activity3_request', 'key_val': r() },
            {'tid': tid, 'key_name': 'activity3_req_open', 'key_val': r() },
            {'tid': tid, 'key_name': 'activity3_req_close', 'key_val': r() }
        ]
        #保存到数据库
        if project_inf.replace(data) < 0:
            return { "msg": "插入project_inf失败" }
    #返回data字典的数据到前端
    return {
        'request': f(data, 'activity3_request'),
        'open': f(data, 'activity3_req_open'),
        'close': f(data, 'activity3_req_close')
    }
@app.route('/<int:tid>/activity/git_issues', methods=['GET','PUT'])
def activity_git_issues(tid):
    data = None
    if request.method == 'GET':
        #查询项目信息表中键为activity4_开头的数据
        data = project_inf.findby_tid_key(tid, 'activity4_')
    if data is None or len(data) == 0:
        #请求为PUT或库中没有数据时去爬虫获取，爬完返回构造data字典：
        # 改为github_url
        # data = gt.get(tid, 'https://github.com/rabbitmq/rabbitmq-server')
        data = [
            {'tid': tid, 'key_name': 'activity4_issues', 'key_val': r() },
            {'tid': tid, 'key_name': 'activity4_iss_open', 'key_val': r() },
            {'tid': tid, 'key_name': 'activity4_iss_close', 'key_val': r() }
        ]
        #保存到数据库
        if project_inf.replace(data) < 0:
            return { "msg": "插入project_inf失败" }
    #返回data字典的数据到前端
    return {
        'issues': f(data, 'activity4_issues'),
        'open': f(data, 'activity4_iss_open'),
        'close': f(data, 'activity4_iss_close')
    }
### 博客论坛书籍搜索
@app.route('/<int:tid>/activity/blogs', methods=['GET','PUT'])
def activity_blogs(tid):
    data = None
    if request.method == 'GET':
        #查询项目信息表中键为info_开头的数据
        data = project_inf.findby_tid_key(tid, 'activity_blogs')
    if data is None or len(data) == 0:
        #请求为PUT或库中没有数据时去爬虫获取，爬完返回构造data字典：
        data = [
            {'tid': tid, 'key_name': 'activity_blogs', 'key_val': '{ "51CTO论坛": '+str(r())+', "CSDN论坛": '+str(r())+', "ITPUB": '+str(r())+', "ChinaUnix": '+str(r())+', "SegmentFault": '+str(r())+', "StackOverFlow": '+str(r())+' }'}
        ]
        #保存到数据库
        if project_inf.replace(data) < 0:
            return { "msg": "插入project_inf失败" }
    #返回data字典的数据到前端
    return json.loads(f(data, 'activity_blogs'))
@app.route('/<int:tid>/activity/bbs', methods=['GET','PUT'])
def activity_bbs(tid):
    data = None
    if request.method == 'GET':
        #查询项目信息表中键为info_开头的数据
        data = project_inf.findby_tid_key(tid, 'activity_bbs')
    if data is None or len(data) == 0:
        #请求为PUT或库中没有数据时去爬虫获取，爬完返回构造data字典：
        res = task_record.findbyid(tid)
        tag = res[0]['keywords']
        sta = os.system('./spidertool/get_bbs.sh ' + tag)
        print 'sta:%s' %(sta)
        if (sta == 0):
            data = spidertool.handle_bbs.get_data()
            print data
        # data = [
        #     {'tid': tid, 'key_name': 'activity_bbs', 'key_val': '{"51CTO论坛":'+str(r())+',"CSDN论坛":'+str(r())+',"ITPUB":'+str(r())+',"ChinaUnix":'+str(r())+',"SegmentFault":'+str(r())+',"StackOverFlow":'+str(r())+'}'}
        # ]
        #保存到数据库
        if project_inf.replace(data) < 0:
            return { "msg": "插入project_inf失败" }
    #返回data字典的数据到前端
    return json.loads(f(data, 'activity_bbs'))
@app.route('/<int:tid>/activity/books', methods=['GET','PUT'])
def activity_books(tid):
    data = None
    if request.method == 'GET':
        #查询项目信息表中键为info_开头的数据
        data = project_inf.findby_tid_key(tid, 'activity_books')
    if data is None or len(data) == 0:
        #请求为PUT或库中没有数据时去爬虫获取，爬完返回构造data字典：
        data = [
            {'tid': tid, 'key_name': 'activity_books', 'key_val': '{"当当图书":'+str(r())+',"书问":'+str(r())+',"百度阅读":'+str(r())+',"新浪爱问":'+str(r())+',"京东图书":'+str(r())+',"亚马逊":'+str(r())+'}'}
        ]
        #保存到数据库
        if project_inf.replace(data) < 0:
            return { "msg": "插入project_inf失败" }
        #返回data字典的数据到前端
    return json.loads(f(data, 'activity_books'))
@app.route('/<int:tid>/activity/searchs', methods=['GET','PUT'])
def activity_searchs(tid):
    data = None
    if request.method == 'GET':
        #查询项目信息表中键为info_开头的数据
        data = project_inf.findby_tid_key(tid, 'activity_searchs')
    if data is None or len(data) == 0:
        #请求为PUT或库中没有数据时去爬虫获取，爬完返回构造data字典：
        data = [
            {'tid': tid, 'key_name': 'activity_searchs', 'key_val': '{"百度":'+str(r())+',"必应":'+str(r())+',"搜狗":'+str(r())+',"360搜索":'+str(r())+',"雅虎":'+str(r())+',"谷歌":'+str(r())+'}'}
        ]
        #保存到数据库
        if project_inf.replace(data) < 0:
            return { "msg": "插入project_inf失败" }
    #返回data字典的数据到前端
    return json.loads(f(data, 'activity_searchs'))
### 代码信息
@app.route('/<int:tid>/code/info', methods=['GET','PUT'])
def code_info(tid):
    data = None
    if request.method == 'GET':
        #查询项目信息表中键为info_开头的数据
        data = project_inf.findby_tid_key(tid, 'code_')
    if data is None or len(data) == 0:
        #库中没有数据时去爬虫获取，爬完返回构造data字典：
        res = task_record.findbyid(tid)
        openhub_url = res[0]['openhub']
        # openhub_url = 'https://www.openhub.net/p/apache-kafka'
        data = spidertool.codeInfo.get(tid, openhub_url + '/analyses/latest/languages_summary')
        # data = [
        #     {'tid': tid, 'key_name': 'info_lines', 'key_val': 419228 },
        #     {'tid': tid, 'key_name': 'info_languages', 'key_val': '{ "Java": "65.2%", "Scala": "27.7%", "HTML": "2.7%", "Python": "3.2%", "shell": "0.6%", "XML": "0.4%", "DOS": "0.2%", "XSL": "0.0%", "Ruby": "0.0%", "JavaScript": "0.0%" }' },
        #     {'tid': tid, 'key_name': 'info_codes', 'key_val': 275037 },
        #     {'tid': tid, 'key_name': 'info_comments', 'key_val': 87369 },
        #     {'tid': tid, 'key_name': 'info_blanks', 'key_val': 56822 },
        #     {'tid': tid, 'key_name': 'info_pcode', 'key_val': '65.6%' },
        #     {'tid': tid, 'key_name': 'info_pcomment', 'key_val': '20.8%' },
        #     {'tid': tid, 'key_name': 'info_pblank', 'key_val': '13.6%' }
        # ]
        #保存到数据库
        if project_inf.replace(data) < 0:
            return { "msg": "插入project_inf失败" }
    #返回data字典的数据到前端
    return {
        "lines": f(data, 'info_lines'),
        "languages": len(json.loads(f(data, 'info_languages')).keys()),
        "codes": f(data, 'info_codes'),
        "comments": f(data, 'info_comments'),
        "blanks": f(data, 'info_blanks'),
        "pcode": f(data, 'info_pcode'),
        "pcomment": f(data, 'info_pcomment'),
        "pblank": f(data, 'info_pblank')
    }
@app.route('/<int:tid>/code/languages', methods=['GET','PUT'])
def code_languages(tid):
    data = None
    if request.method == 'GET':
        #查询项目信息表中键为info_开头的数据
        data = project_inf.findby_tid_key(tid, 'info_languages')
    if data is None or len(data) == 0:
        #库中没有数据时去爬虫获取，爬完返回构造data字典：

        res = task_record.findbyid(tid)
        openhub_url = res[0]['openhub']
        # openhub_url = 'https://www.openhub.net/p/apache-kafka'

        data = cl.get(tid, openhub_url + '/analyses/latest/languages_summary')
        # data = [
        #     {'tid': tid, 'key_name': 'info_languages', 'key_val': '{ "Java": "65.2%", "Scala": "27.7%", "HTML": "2.7%", "Python": "3.2%", "shell": "0.6%", "XML": "0.4%", "DOS": "0.2%", "XSL": "0.0%", "Ruby": "0.0%", "JavaScript": "0.0%" }' },
        # ]
        #保存到数据库
        if project_inf.replace(data) < 0:
            return { "msg": "插入project_inf失败" }
    #返回data字典的数据到前端
    return json.loads(f(data, 'info_languages'))
@app.route('/<int:tid>/code/by_date', methods=['GET','PUT'])
def code_by_date(tid):
    data = None
    if request.method == 'GET':
        #查询项目代码信息表
        data = code_date.findby_tid(tid)
    if data is None or len(data) == 0:
        #库中没有数据时去爬虫获取，爬完返回构造data字典：
        data = [
            {'tid': tid, 'd': '2011-08-01', 'codes': 53610, 'comments': 8887, 'blanks': 8614},
            {'tid': tid, 'd': '2011-09-01', 'codes': 62608, 'comments': 14277, 'blanks': 10115},
            {'tid': tid, 'd': '2011-10-01', 'codes': 28450, 'comments': 13729, 'blanks': 5574},
            {'tid': tid, 'd': '2011-11-01', 'codes': 28376, 'comments': 13744, 'blanks': 5592},
            {'tid': tid, 'd': '2011-12-01', 'codes': 28390, 'comments': 13780, 'blanks': 5597},
            {'tid': tid, 'd': '2012-01-01', 'codes': 29004, 'comments': 13901, 'blanks': 5768},
            {'tid': tid, 'd': '2012-02-01', 'codes': 29502, 'comments': 14051, 'blanks': 5900},
            {'tid': tid, 'd': '2012-03-01', 'codes': 29550, 'comments': 14028, 'blanks': 5904},
            {'tid': tid, 'd': '2012-04-01', 'codes': 29850, 'comments': 14115, 'blanks': 6014},
            {'tid': tid, 'd': '2012-05-01', 'codes': 29851, 'comments': 14115, 'blanks': 6014},
            {'tid': tid, 'd': '2012-06-01', 'codes': 29867, 'comments': 14115, 'blanks': 6017},
            {'tid': tid, 'd': '2012-07-01', 'codes': 29919, 'comments': 14253, 'blanks': 6019},
            {'tid': tid, 'd': '2012-08-01', 'codes': 30114, 'comments': 14289, 'blanks': 6068},
            {'tid': tid, 'd': '2012-09-01', 'codes': 16557, 'comments': 6466, 'blanks': 3595},
            {'tid': tid, 'd': '2012-10-01', 'codes': 16558, 'comments': 6464, 'blanks': 3595},
            {'tid': tid, 'd': '2012-11-01', 'codes': 25818, 'comments': 9621, 'blanks': 5410},
            {'tid': tid, 'd': '2012-12-01', 'codes': 26811, 'comments': 10159, 'blanks': 5536},
            {'tid': tid, 'd': '2013-01-01', 'codes': 28889, 'comments': 10987, 'blanks': 5927},
            {'tid': tid, 'd': '2013-02-01', 'codes': 28899, 'comments': 10987, 'blanks': 5927},
            {'tid': tid, 'd': '2013-03-01', 'codes': 29694, 'comments': 11135, 'blanks': 6027},
            {'tid': tid, 'd': '2013-04-01', 'codes': 29949, 'comments': 11204, 'blanks': 6046},
            {'tid': tid, 'd': '2013-05-01', 'codes': 29949, 'comments': 11204, 'blanks': 6046},
            {'tid': tid, 'd': '2013-06-01', 'codes': 29949, 'comments': 11204, 'blanks': 6046},
            {'tid': tid, 'd': '2013-07-01', 'codes': 30780, 'comments': 11547, 'blanks': 6126},
            {'tid': tid, 'd': '2013-08-01', 'codes': 30781, 'comments': 11550, 'blanks': 6127},
            {'tid': tid, 'd': '2013-09-01', 'codes': 31579, 'comments': 11713, 'blanks': 6246},
            {'tid': tid, 'd': '2013-10-01', 'codes': 31533, 'comments': 11669, 'blanks': 6237},
            {'tid': tid, 'd': '2013-11-01', 'codes': 32225, 'comments': 11840, 'blanks': 6360},
            {'tid': tid, 'd': '2013-12-01', 'codes': 32393, 'comments': 11858, 'blanks': 6363},
            {'tid': tid, 'd': '2014-01-01', 'codes': 32607, 'comments': 12009, 'blanks': 6398},
            {'tid': tid, 'd': '2014-02-01', 'codes': 42835, 'comments': 16224, 'blanks': 8101},
            {'tid': tid, 'd': '2014-03-01', 'codes': 45397, 'comments': 16734, 'blanks': 8569},
            {'tid': tid, 'd': '2014-04-01', 'codes': 45329, 'comments': 17170, 'blanks': 8663},
            {'tid': tid, 'd': '2014-05-01', 'codes': 46140, 'comments': 18001, 'blanks': 8822},
            {'tid': tid, 'd': '2014-06-01', 'codes': 46500, 'comments': 18414, 'blanks': 8945},
            {'tid': tid, 'd': '2014-07-01', 'codes': 48457, 'comments': 18870, 'blanks': 9345},
            {'tid': tid, 'd': '2014-08-01', 'codes': 49074, 'comments': 19182, 'blanks': 9543},
            {'tid': tid, 'd': '2014-09-01', 'codes': 49128, 'comments': 19169, 'blanks': 9527},
            {'tid': tid, 'd': '2014-10-01', 'codes': 49751, 'comments': 19543, 'blanks': 9676},
            {'tid': tid, 'd': '2014-11-01', 'codes': 50330, 'comments': 19784, 'blanks': 9809},
            {'tid': tid, 'd': '2014-12-01', 'codes': 51289, 'comments': 20232, 'blanks': 10023},
            {'tid': tid, 'd': '2015-01-01', 'codes': 53915, 'comments': 20539, 'blanks': 10420},
            {'tid': tid, 'd': '2015-02-01', 'codes': 53236, 'comments': 21324, 'blanks': 10768},
            {'tid': tid, 'd': '2015-03-01', 'codes': 55955, 'comments': 21869, 'blanks': 11273},
            {'tid': tid, 'd': '2015-04-01', 'codes': 57056, 'comments': 22446, 'blanks': 11690},
            {'tid': tid, 'd': '2015-05-01', 'codes': 58405, 'comments': 22622, 'blanks': 11826},
            {'tid': tid, 'd': '2015-06-01', 'codes': 59432, 'comments': 22847, 'blanks': 12045},
            {'tid': tid, 'd': '2015-07-01', 'codes': 62581, 'comments': 23999, 'blanks': 12833},
            {'tid': tid, 'd': '2015-08-01', 'codes': 73048, 'comments': 28113, 'blanks': 15096},
            {'tid': tid, 'd': '2015-09-01', 'codes': 83422, 'comments': 32074, 'blanks': 17939},
            {'tid': tid, 'd': '2015-10-01', 'codes': 96824, 'comments': 35863, 'blanks': 20265},
            {'tid': tid, 'd': '2015-11-01', 'codes': 102306, 'comments': 36932, 'blanks': 21604},
            {'tid': tid, 'd': '2015-12-01', 'codes': 105447, 'comments': 37784, 'blanks': 22795},
            {'tid': tid, 'd': '2016-01-01', 'codes': 109341, 'comments': 39157, 'blanks': 23955},
            {'tid': tid, 'd': '2016-02-01', 'codes': 115928, 'comments': 41141, 'blanks': 25386},
            {'tid': tid, 'd': '2016-03-01', 'codes': 120573, 'comments': 42589, 'blanks': 26433},
            {'tid': tid, 'd': '2016-04-01', 'codes': 127393, 'comments': 45590, 'blanks': 28075},
            {'tid': tid, 'd': '2016-05-01', 'codes': 130564, 'comments': 46462, 'blanks': 28839},
            {'tid': tid, 'd': '2016-06-01', 'codes': 133896, 'comments': 46978, 'blanks': 29631},
            {'tid': tid, 'd': '2016-07-01', 'codes': 137657, 'comments': 48162, 'blanks': 30510},
            {'tid': tid, 'd': '2016-08-01', 'codes': 142001, 'comments': 49097, 'blanks': 31375},
            {'tid': tid, 'd': '2016-09-01', 'codes': 152552, 'comments': 51257, 'blanks': 33415},
            {'tid': tid, 'd': '2016-10-01', 'codes': 155327, 'comments': 51707, 'blanks': 34010},
            {'tid': tid, 'd': '2016-11-01', 'codes': 156804, 'comments': 52017, 'blanks': 34344},
            {'tid': tid, 'd': '2016-12-01', 'codes': 160592, 'comments': 54475, 'blanks': 35241},
            {'tid': tid, 'd': '2017-01-01', 'codes': 178927, 'comments': 60510, 'blanks': 38740},
            {'tid': tid, 'd': '2017-02-01', 'codes': 181589, 'comments': 61994, 'blanks': 38756},
            {'tid': tid, 'd': '2017-03-01', 'codes': 189059, 'comments': 63873, 'blanks': 40210},
            {'tid': tid, 'd': '2017-04-01', 'codes': 201575, 'comments': 66461, 'blanks': 43027},
            {'tid': tid, 'd': '2017-05-01', 'codes': 226972, 'comments': 73203, 'blanks': 47929},
            {'tid': tid, 'd': '2017-06-01', 'codes': 236859, 'comments': 75343, 'blanks': 49865},
            {'tid': tid, 'd': '2017-07-01', 'codes': 245905, 'comments': 78787, 'blanks': 51580},
            {'tid': tid, 'd': '2017-08-01', 'codes': 255144, 'comments': 80877, 'blanks': 53318},
            {'tid': tid, 'd': '2017-09-01', 'codes': 269438, 'comments': 86433, 'blanks': 56033},
            {'tid': tid, 'd': '2017-10-01', 'codes': 275037, 'comments': 87369, 'blanks': 56822}
        ]
        #保存到数据库
        code_date.deleteby_tid(tid)
        if code_date.insert(data) < 0:
            return { "msg": "插入code_date失败" }
    # return data
    return q('2.5.3.json')
@app.route('/<int:tid>/code/by_tag', methods=['GET','PUT'])
def code_by_tag(tid):
    data = None
    if request.method == 'GET':
        #查询项目代码信息表
        data = code_ver.findby_tid(tid)
    if data is None or len(data) == 0:
        #库中没有数据时去爬虫获取，爬完返回构造data字典：
        data = [
            {'tid': tid, 'ver': 'v1', 'd': '2016-01-01', 'codes': r(), 'comments': r(), 'blanks': r()},
            {'tid': tid, 'ver': 'v2', 'd': '2016-02-01', 'codes': r(), 'comments': r(), 'blanks': r()},
            {'tid': tid, 'ver': 'v3', 'd': '2016-03-01', 'codes': r(), 'comments': r(), 'blanks': r()},
            {'tid': tid, 'ver': 'v4', 'd': '2016-04-01', 'codes': r(), 'comments': r(), 'blanks': r()}
        ]
        #保存到数据库
        code_ver.deleteby_tid(tid)
        if code_ver.insert(data) < 0:
            return { "msg": "插入code_ver失败" }
    return data
#安全性
@app.route('/<int:tid>/security/info', methods=['GET','PUT'])
def security_info(tid):
    data = None
    if request.method == 'GET':
        #查询项目代码信息表
        data = se_info.findby_tid(tid)
    if data is None or len(data) == 0:
        #库中没有数据时去爬虫获取，爬完返回构造data字典：
        data = [
            {'tid': tid, 'cve': 'cve111', 'cncve': 'cncve111', 'en_url': 'http://en_url', 'zh_url': 'http://zh_url', 'ptime': '2017-02-02', 'level': '中危', 'description': 'Pivotal RabbitMQ中存在跨站脚本漏洞'},
            {'tid': tid, 'cve': 'cve111', 'cncve': 'cncve111', 'en_url': 'http://en_url', 'zh_url': 'http://zh_url', 'ptime': '2017-04-02', 'level': '高危', 'description': 'Pivotal RabbitMQ中存在跨站脚本漏洞'},
            {'tid': tid, 'cve': 'cve111', 'cncve': 'cncve111', 'en_url': 'http://en_url', 'zh_url': 'http://zh_url', 'ptime': '2017-06-02', 'level': '低危', 'description': 'Pivotal RabbitMQ中存在跨站脚本漏洞'},
            {'tid': tid, 'cve': 'cve111', 'cncve': 'cncve111', 'en_url': 'http://en_url', 'zh_url': 'http://zh_url', 'ptime': '2017-12-02', 'level': '中危', 'description': 'Pivotal RabbitMQ中存在跨站脚本漏洞'}
        ]
        #保存到数据库
        if se_info.replace(data) < 0:
            return { "msg": "插入se_info失败" }
    return data


########## 主函数
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=True)
